<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<!-- <meta name="viewport" content="width=device-width, initial-scale=1"> -->
	<title>画画</title>
	<style>
		* {
			margin: 0;
			padding: 0;
			box-sizing: border-box;
		}
		.container {
			position: absolute;
			top: 0;
			bottom: 0;
			left: 0;
			right: 0;

			/* touch-action: none; */
		}
		.tools {
			background-color: #999;
			height: 7.3rem;
			padding: 0.5rem;
			position: relative;
			font-size: 4rem;

			z-index: 7;
			display: flex;
		}
		.tools .left {
			flex: 1;

			display: flex;
		}
		.tools .right {
			/*width: 12rem;*/
			flex-shrink: 0;

			display: flex;
			justify-content: space-between;
		}
		.tools .tool-item {
			background-color: #fff;
			margin: 0 1rem 0 0;
			padding: 0.5rem 0;
			border-radius: 0.5rem;
			/* line-height: 3rem; */
			cursor: pointer;
			font-weight: bold;
		}
		.tools .tool-item:hover {
			background-color: #ccc;
			color: #fff;
		}
		.tools .tool-item.selected {
			background-color: #a00;
			color: #fff;
		}
		.tools .clear-btn {
			margin-right: 2rem;
		}
		.tool-panel {
			position: relative;
			z-index: 8;
			padding: 2rem 0.5rem;
			background-color: #ddd;
		}
		.width-box {
			max-width: 50rem;
			font-size: 0;
		}
		.width-box .line-box {
			display: inline-block;
			cursor: pointer;
			width: 24.5rem;
			margin: 0.5rem 0.5rem 0.5rem 0;
		}
		.line-box .line {
			background-color: #000;
			display: inline-block;
			width: 100%;
			border-radius: 5rem 5rem 5rem 5rem;
		}
		.color-box {
			font-size: 0;
			max-width: 88rem;
		}
		.color-box .color {
			width: 10rem;
			height: 10rem;
			border-radius: 50%;
			display: inline-block;
			margin: 0 1rem 1rem 0;
		}
		.content {
			position: absolute;

			top: 7.3rem;
			bottom: 0;
			left: 0;
			right: 0;
			z-index: 1;

			/* Safari */
			-webkit-user-select: none;
			/* Firefox */
			-moz-user-select: none;
			/* IE10+/Edge */
			-ms-user-select: none;
			/* Standard syntax */
			user-select: none;

			touch-action: none;
		}
		.ca {
			display: block;
			/* border: 0.1rem solid #ccc; */
			margin: 0 auto;
			cursor: default;
		}
		.bg-ca {
			position: absolute;
			z-index: -1;
			top: 0px;
		}
		.download-box {
			background-color: #6666;
			position: absolute;
			top: 0;
			bottom: 0;
			left: 0;
			right: 0;
			z-index: 9;
		}
		.download-content {
			padding: 1rem;
			/* width: 50rem; */
			width: 80%;
			margin: 20rem auto;
			font-size: 3rem;
			background-color: #fff;
			border-radius: 0.5rem;
		}
		.download-tip {
			display: inline-block;
		}
		.download-link {
			display: block;
			margin: 2rem 0;
			font-size: 6rem;
			word-break: break-all;
		}
		.download-close {
			margin-top: 1rem;
			width: 10rem;
			text-align: center;
			color: red;
			border: 0.1rem solid red;
			border-radius: 0.5rem;
			cursor: pointer;
			display: inline-block;
		}
	</style>
</head>
<body>
<div class="container">
	<div class="tools">
		<div class="left">
			<div class="tool-item width-btn">粗细</div>
			<div class="tool-item color-btn">颜色</div>
			<div class="tool-item pencil-btn selected">画笔</div>
			<div class="tool-item rubber-btn">橡皮</div>
		</div>
		<div class="right">
			<div class="tool-item import-img-btn">
				<span>导入</span>
				<input type="file" style="display: none">
			</div>
			<div class="tool-item bg-img-btn">
				<span>背景</span>
				<input type="file" style="display: none">
			</div>
			<div class="tool-item clear-btn">重置</div>
			<div class="tool-item save-btn">保存</div>
		</div>
	</div>
	<div class="tool-panel" style="display: none;">
		<div class="width-box" style="display: none;">
			<div class="line-box" >
				<div class="line" style="height: 1px"></div>
			</div>
			<div class="line-box" >
				<div class="line" style="height: 4px"></div>
			</div>
			<div class="line-box" >
				<div class="line" style="height: 10px"></div>
			</div>
		</div>
		<div class="color-box" style="display: none;">
			<div class="color" style="background-color: #ff0000;"></div>
			<div class="color" style="background-color: #00ff00;"></div>
			<div class="color" style="background-color: #0000ff;"></div>
		</div>
	</div>

	<div class="content">
		<canvas id="ca" class="ca" width="600px" height="600px" >您的浏览器不支持 Canvas</canvas>
		<canvas id="bgCa" class="bg-ca" style="left: 5px;" width="600px" height="600px"></canvas>
	</div>
	<div class="download-box" style="display: none;">
		<div class="download-content" >
			<div class="download-tip">图片保存</div>
			<div class="download-close" >关闭</div>
			<a class="download-link" href="">未命名123456.png</a>
			<img src="" id="save-img" style="display: none" alt="no image" >
		</div>
	</div>
</div>
<script>
	let draw;
	(function (global) {
		let widthBox,colorBox;
		let downloadBox,downloadLink,downloadClose;
		let saveImg;

		function initCanvas() {
			let contentDiv = document.getElementsByClassName('content')[0];
			let toolPanelDiv = document.getElementsByClassName('tool-panel')[0];
			let ca = document.getElementById('ca');
			const ctx = ca.getContext("2d");
			let bgCa = document.getElementById('bgCa');

			let draw = {
				// canvas 与 page 的偏移
				offsetLeft: ca.offsetLeft,
				offsetTop: contentDiv.offsetTop,

				contentDiv: contentDiv,
				toolPanelDiv: toolPanelDiv,
				ca: ca,
				ctx: ctx,
				bgCa: bgCa,

				selectedLineWidth: 2,
				selectedColor: '#000',
				// 橡皮
				isRubber: false,
				
				drawing: false,
				prePoint: null,

				resetBgCanvasSize: function () {
					this.bgCa.width = this.ca.width;
					this.bgCa.height = this.ca.height;
					this.bgCa.style.left = this.offsetLeft + "px";

					this.resetOffsetBgCanvas();
				},
				resetOffsetBgCanvas: function(){
					this.bgCa.style.left = this.ca.offsetLeft + "px";
				},
				clearBgCanvas: function () {
					let ctx = this.bgCa.getContext('2d');
					ctx.clearRect(0, 0, this.bgCa.width, this.bgCa.height);
				},

				resetCanvasSize: function () {
					this.ca.width = this.contentDiv.offsetWidth - 10;
					this.ca.height = this.contentDiv.offsetHeight - 10;
					this.resetOffset();
				},
				resetOffset: function () {
					this.offsetTop = this.contentDiv.offsetTop;
					this.offsetLeft = this.ca.offsetLeft;
				},
				getMousePointForCanvas: function (pageX, pageY) {
					let x = pageX - this.offsetLeft;
					let y = pageY - this.offsetTop;
					return {x, y};
				},
				mousedown: function(e, pageX, pageY){
					this.drawing = true;
					// 线段末端的属性, round 线段末端以圆形结束
					this.ctx.lineCap = "round";
					// 设置2个长度不为0的相连部分如何连接在一起的属性, round 圆弧
					this.ctx.lineJoin = "round";
					this.ctx.lineWidth = this.selectedLineWidth;

					this.ctx.strokeStyle = this.selectedColor;
					if (this.isRubber) {
						// 擦除模式
						this.ctx.globalCompositeOperation = 'destination-out';
					} else {
						// 默认值, 后面的颜色覆盖前面的颜色
						this.ctx.globalCompositeOperation = 'source-over';
						// 两个重叠图形的颜色是通过颜色值相加来确定的
						//this.ctx.globalCompositeOperation = 'lighter';
					}

					// console.log('draw:', draw);
					let p = this.getMousePointForCanvas(pageX, pageY);

					this.prePoint = p;

					this.ctx.beginPath();
					this.ctx.moveTo(this.prePoint.x, this.prePoint.y);
					this.ctx.lineTo(p.x, p.y);
					this.ctx.stroke();
				},
				mouseup: function(e, pageX, pageY){
					this.drawing = false;
				},
				mousemove: function (e, pageX, pageY) {
					if (this.drawing) {
						let p = this.getMousePointForCanvas(pageX, pageY);

						this.ctx.beginPath();
						this.ctx.moveTo(this.prePoint.x, this.prePoint.y);
						this.ctx.lineTo(p.x, p.y);
						this.ctx.stroke();
						this.ctx.closePath();

						this.prePoint = p;
					}
				},
				mouseleave: function (e, pageX, pageY) {
					this.drawing = false;
				},
				clearCanvas: function () {
					this.ctx.clearRect(0, 0, this.ca.width, this.ca.height);
				},
				saveImage: function(){
					let imageName = prompt('请为图片命名', '未命名');
					if (imageName === null || imageName === undefined) {
						return;
					}
					if (imageName.trim().length == 0) {
						imageName = '未命名';
					}

					this.ca.toBlob( (blob) => {
						let url = URL.createObjectURL(blob);
						downloadLink.href = url;
						downloadLink.download = imageName + '.png';
						downloadLink.innerText = downloadLink.download;

						//downloadBox.style.display = 'block';
					});

					saveImg.src = this.ca.toDataURL('image/png', 1);
					downloadBox.style.display = 'block';
				}
			};
			return draw;
		}

		function bindToolBtns() {
			let widthBtn = document.getElementsByClassName('width-btn')[0];
			widthBtn.onclick = function () {
				draw.toolPanelDiv.style.display = null;

				colorBox.style.display = 'none';
				widthBox.style.display = null;
			}
			let colorBtn = document.getElementsByClassName('color-btn')[0];
			colorBtn.onclick = function () {
				draw.toolPanelDiv.style.display = null;

				widthBox.style.display = 'none';
				colorBox.style.display = null;
			}

			let pencilBtn = document.getElementsByClassName('pencil-btn')[0];
			pencilBtn.onclick = function (){
				draw.isRubber = false;
				rubberBtn.classList.remove('selected');
				pencilBtn.classList.add('selected');
			}
			let rubberBtn = document.getElementsByClassName('rubber-btn')[0];
			rubberBtn.onclick = function (){
				draw.isRubber = true;
				pencilBtn.classList.remove('selected');
				rubberBtn.classList.add('selected');
			}

			let importImgBtn = document.getElementsByClassName('import-img-btn')[0];
			importImgBtn.onclick = function () {
				let input = importImgBtn.children[1];
				input.onchange = function(){
					let f = input.files[0];
					if (f && f.type.startsWith("image")) {
						//console.log('f:', f);
						let image = new Image();
						image.onload = function(){
							//console.log('image:', image.width, image.height);
							// 缩放展示
							let width = draw.ca.width - 20;
							let height = draw.ca.height - 20;
							// 保持 height 不变
							let newWidth = image.width/image.height * height;
							if (newWidth > width) {
								// 宽不够, 则 保持 width 不变
								let newHeight = width / (image.width/image.height);
								if (newHeight > height) {
									// 宽高 都不够, 则 缩放 TODO: ??

								} else {
									height = newHeight;
								}
							} else {
								width = newWidth;
							}
							draw.clearCanvas();
							draw.ctx.drawImage(image, 10, 10, width, height);
							image = undefined;
						};
						image.src = URL.createObjectURL(f);
					}
				}
				input.click();
			}
			// bg-img-btn
			let bgImgBtn = document.getElementsByClassName('bg-img-btn')[0];
			bgImgBtn.onclick = function () {
				let input = bgImgBtn.children[1];
				input.onchange = function(){
					let f = input.files[0];
					if (f && f.type.startsWith("image")) {
						//console.log('f:', f);
						let image = new Image();
						image.onload = function(){
							//console.log('image:', image.width, image.height);
							// 缩放展示
							let width = draw.ca.width - 20;
							let height = draw.ca.height - 20;
							// 保持 height 不变
							let newWidth = image.width/image.height * height;
							if (newWidth > width) {
								// 宽不够, 则 保持 width 不变
								let newHeight = width / (image.width/image.height);
								if (newHeight > height) {
									// 宽高 都不够, 则 缩放 TODO: ??

								} else {
									height = newHeight;
								}
							} else {
								width = newWidth;
							}
							
							draw.clearBgCanvas();
							let ctx = draw.bgCa.getContext('2d');
							ctx.drawImage(image, 10, 10, width, height);
							image = undefined;
						};
						image.src = URL.createObjectURL(f);
					}
				}
				input.click();
			}
			let clearBtn = document.getElementsByClassName('clear-btn')[0];
			clearBtn.onclick = function (){
				draw.clearCanvas();
				draw.resetCanvasSize();

				draw.clearBgCanvas();
				draw.resetBgCanvasSize();
			}
			let saveBtn = document.getElementsByClassName('save-btn')[0];
			saveBtn.onclick = function (){
				draw.saveImage();
			}
		}

		function initWidthBox() {
			let lineArr = [1,2,4,6,8,10,14,26,50,80];
			//let lineArr = [1,2,4,6,8,10,15,20,25,30,40,50];
			let html = '';
			for(let i=0; i<lineArr.length; i++) {
				let ht = lineArr[i];
				html += `<div class="line-box" style="height: ${ht/10+6}rem" ><div class="line" style="height: ${ht}px"></div></div>`;
			}
			widthBox.innerHTML = html;
			let wArr = widthBox.getElementsByClassName('line-box');
			for(let i=0; i<wArr.length; i++) {
				wArr[i].onclick = function () {
					let line = this.firstElementChild;
					draw.selectedLineWidth = parseInt(line.style.height);
					widthBox.style.display = 'none';
				}
			}
		}
		function initColorBox() {
			//let colorArr = ['#000', '#fff', '#f00', '#0f0', '#00f'];
			// 24色: 黑、棕色、大红、浅桔红、橙色、金黄、浅橙色、浅黄、荧光黄、米绿、军绿、浅绿、淡绿、梅绿、水蓝、淡蓝、天蓝、老蓝、紫色、艳红、梅红、桃红、肉色、灰色
			// let colorArr = [
			// 	'#000000','#A52A2A','#FF0000','#FFA500','#FFA500','#FFFF00',
			// 	'#FFB6C1','#FFFFE0','#FFFF00','#C1D8C1','#4B5320','#90EE90',
			// 	'#98FB98','#008F8F','#00FFFF','#ADD8E6','#87CEEB','#232B88',
			// 	'#800080','#FF007F','#FF1493','#FFC0CB','#FFB6C1','#808080'
			// ];
			// 48色水彩笔
			let colorArr = [
				'#010101','#110972','#ffffff','#055545','#26ab10','#06c3e1',
				'#ffe013','#fe6006','#bb090b','#fe3675','#e71437','#3a1011',
				'#1f1f1f','#43105a','#123510','#83de37','#0f0a45','#faf809',
				'#fc9c12','#f74a67','#9f1819','#47250c','#6d3900','#2f1320',
				'#2c0d3d','#c00e38','#191205','#101a5b','#022e29','#296621',
				'#0d4a49','#6d3900','#301321','#ef1062','#da1555','#170804',
				'#555d54','#1f1d60','#380f45','#20052a','#09340d','#1d746e',
				'#0b7027','#2f0f2a','#b21b03','#f07f7e','#5e4d1a','#d5341f'
			];
			let html = '';
			for(let i=0; i<colorArr.length; i++) {
				let cr = colorArr[i];
				html += `<div class="color" style="background-color: ${cr};"></div>`;
			}
			colorBox.innerHTML = html;
			let cArr = colorBox.getElementsByClassName('color');
			for(let i=0; i<cArr.length; i++) {
				cArr[i].onclick = function () {
					let color = this.style.backgroundColor;
					draw.selectedColor = color;
					colorBox.style.display = 'none';
				}
			}
		}

		function resetHtmlSize () {
			let rootEl = document.getElementsByTagName('html')[0];
			let docEl = document.documentElement;
			let cw = docEl.clientWidth;
			if (cw > 750) {
				cw = 750;
			}
			let rem = cw / 750 * 10;
			// 1rem = 10px
    		rootEl.style.fontSize = rem + 'px';
		}

		global.onclick = function(e) {
			let target = e.target;
			//console.log(target);
			if ( !target.className.includes('width-btn') 
				&& !target.className.includes('color-btn')
				&& !target.className.includes('tool-panel')
				&& !target.className.includes('width-box')
				&& !target.className.includes('color-box')
				) {
				let display = draw.toolPanelDiv.style.display;
				if (display !== 'none') {
					draw.toolPanelDiv.style.display = 'none';
					widthBox.style.display = 'none';
					colorBox.style.display = 'none';
				}
			}
		}

		global.onload = function () {
			widthBox = document.getElementsByClassName('width-box')[0];
			colorBox = document.getElementsByClassName('color-box')[0];

			downloadBox = document.getElementsByClassName('download-box')[0];
			downloadLink = document.getElementsByClassName('download-link')[0];
			downloadClose = document.getElementsByClassName('download-close')[0];

			saveImg = document.getElementById('save-img');

			resetHtmlSize();
			draw = initCanvas();
			draw.resetCanvasSize();
			draw.resetBgCanvasSize();
			initWidthBox();
			initColorBox();

			draw.ca.addEventListener("mousedown", function(e){
				//console.log('mousedown:', e);
				global.onclick(e);
				draw.mousedown(e, e.pageX, e.pageY);
			}, false);
			draw.ca.addEventListener("mouseup", function(e){
				draw.mouseup(e);
			}, false);
			draw.ca.addEventListener("mousemove", function(e){
				draw.mousemove(e, e.pageX, e.pageY);
			}, false);
			draw.ca.addEventListener("mouseleave", function(e){
				draw.mouseleave(e);
			}, false);

			draw.ca.addEventListener("touchstart", function(e){
				//console.log('touchstart:', e);
				e.cancelable && e.preventDefault();
				global.onclick(e);
				let touches = e.touches;
				if (touches && touches.length>0) {
					let point0 = touches[0];
					draw.mousedown(e, point0.pageX, point0.pageY);
				}
			}, false);
			draw.ca.addEventListener("touchend", function(e){
				draw.mouseup(e);
			}, false);
			draw.ca.addEventListener("touchmove", function(e){
				e.cancelable && e.preventDefault();
				let touches = e.touches;
				if (touches && touches.length>0) {
					let point0 = touches[0];
					draw.mousemove(e, point0.pageX, point0.pageY);
				}
			}, { passive: false });
			draw.ca.addEventListener("touchcancel", function(e){
				//console.log('touchcancel:', e);
			}, false);

			document.addEventListener('wheel', function(e){
				//console.log('wheel:', e);
				if (e.ctrlKey) {
					return;
				}
				// up 放大, down 缩小
				let newWidth = draw.selectedLineWidth + -1*Math.sign(e.deltaY);
				if (newWidth < 1) {
					newWidth = 1;
				}
				if (newWidth > 200) {
					newWidth = 200;
				}
				draw.selectedLineWidth = newWidth;
			});

			downloadClose.addEventListener('click', function () {
				downloadBox.style.display = 'none';
				downloadLink.href = 'javascript:void(0);';
				downloadLink.download = '无';
				downloadLink.innerText = '无';
				saveImg.src = null;
			});
			// downloadLink.addEventListener('click', function () {
			// 	setTimeout(function (){
			// 		let event = new MouseEvent('click');
			// 		downloadClose.dispatchEvent(event);
			// 	}, 100);
			// 	return true;
			// });

			bindToolBtns();
		};
		global.onresize = function() {
			resetHtmlSize();
			if (draw) {
				//draw.resetCanvasSize();
				draw.resetOffset();
				draw.resetOffsetBgCanvas();
			}
		}
	})(window);
	/*
1 白色 #FFFFFF 2 红色 #FF0000 3 绿色 #00FF00
4 蓝色 #0000FF 5 牡丹红 #FF00FF 6 青色 #00FFFF
7 黄色 #FFFF00 8 黑色 #000000 9 海蓝 #70DB93
10 巧克力色 #5C3317 11 蓝紫色 #9F5F9F 12 黄铜色 #B5A642
13 亮金色 #D9D919 14 棕色 #A67D3D 15 青铜色 #8C7853
16 2号青铜色 #A67D3D 17 士官服蓝色 #5F9F9F 18 冷铜色 #D98719
19 铜色 #B87333 20 珊瑚红 #FF7F00 21 紫蓝色 #42426F
22 深棕 #5C4033 23 深绿 #2F4F2F 24 深铜绿色 #4A766E
25 深橄榄绿 #4F4F2F 26 深兰花色 #9932CD 27 深紫色 #871F78
28 深石板蓝 #6B238E 29 深铅灰色 #2F4F4F 30 深棕褐色 #97694F
32 深绿松石色 #7093DB 33 暗木色 #855E42 34 淡灰色 #545454
35 土灰玫瑰红色#856363 36 长石色 #D19275 37 火砖色 #8E2323
38 森林绿 #238E23 39 金色 #CD7F32 40 鲜黄色 #DBDB70
41 灰色 #C0C0C0 42 铜绿色 #527F76 43 青黄色 #93DB70
44 猎人绿 #215E21 45 印度红 #4E2F2F 46 土黄色 #9F9F5F
47 浅蓝色 #C0D9D9 48 浅灰色 #A8A8A8 49 浅钢蓝色 #8F8FBD
59 浅木色 #E9C2A6 60 石灰绿色 #32CD32 61 桔黄色 #E47833
62 褐红色 #8E236B 63 中海蓝色 #32CD99 64 中蓝色 #3232CD
65 中森林绿 #6B8E23 66 中鲜黄色 #EAEAAE 67 中兰花色 #9370DB
68 中海绿色 #426F42 69 中石板蓝色 #7F00FF 70 中春绿色 #7FFF00
71 中绿松石色 #70DBDB 72 中紫红色 #DB7093 73 中木色 #A68064
74 深藏青色 #2F2F4F 75 海军蓝 #23238E 76 霓虹篮 #4D4DFF
77 霓虹粉红 #FF6EC7 78 新深藏青色 #00009C 79 新棕褐色 #EBC79E
80 暗金黄色 #CFB53B 81 橙色 #FF7F00 82 橙红色 #FF2400
83 淡紫色 #DB70DB 84 浅绿色 #8FBC8F 85 粉红色 #BC8F8F
86 李子色 #EAADEA 87 石英色 #D9D9F3 88 艳蓝色 #5959AB
89 鲑鱼色 #6F4242 90 猩红色 #BC1717 91 海绿色 #238E68
92 半甜巧克力色#6B4226 93 赭色 #8E6B23 94 银色 #E6E8FA
95 天蓝 #3299CC 96 石板蓝 #007FFF 97 艳粉红色 #FF1CAE
98 春绿色 #00FF7F 99 钢蓝色 #236B8E 100 亮天蓝色 #38B0DE
101 棕褐色 #DB9370 102 紫红色 #D8BFD8 103 石板蓝色 #ADEAEA
104 浓深棕色 #5C4033 105 淡浅灰色 #CDCDCD 106 紫罗兰色 #4F2F4F
107 紫罗兰红色 #CC3299 108 麦黄色 #D8D8BF 109 黄绿色 #99CC00 ??
	*/
</script>
</body>
</html>